"""
真实场景数据生成器
生成模拟真实生产环境的各种数据
"""
import random
from datetime import datetime, timedelta
from typing import List, Dict, Any
import uuid


class DataGenerator:
    """数据生成器类"""

    # 产品数据库
    PRODUCT_TEMPLATES = [
        {
            "type": "电力电缆",
            "models": [
                "YJV", "YJLV", "YJY", "YJLY", "VV", "VLV", "VY", "VLY",
                "NH-YJV", "NH-YJLV", "ZR-YJV", "ZR-YJLV"
            ],
            "specifications": ["1×25", "1×35", "1×50", "1×70", "1×95", "1×120", "1×150", "1×185",
                             "3×25+1×16", "3×35+1×16", "3×50+1×25", "3×70+1×35", "3×95+1×50",
                             "4×25", "4×35", "4×50", "4×70", "4×95", "5×25", "5×35"],
            "voltage": ["0.6/1kV", "8.7/10kV", "8.7/15kV", "26/35kV"],
            "unit": "米"
        },
        {
            "type": "控制电缆",
            "models": ["KVV", "KVVP", "KVVR", "KVVRP", "KVV22", "KVVP22"],
            "specifications": ["2×0.75", "2×1.0", "2×1.5", "2×2.5", "4×0.75", "4×1.0",
                             "4×1.5", "4×2.5", "7×0.75", "7×1.0", "12×0.75", "19×0.75"],
            "voltage": ["450/750V"],
            "unit": "米"
        },
        {
            "type": "架空线",
            "models": ["JKLYJ", "JL/G1A", "JKLGYJ", "LGJ"],
            "specifications": ["25", "35", "50", "70", "95", "120", "150", "185", "240", "300"],
            "voltage": ["10kV", "35kV"],
            "unit": "米"
        }
    ]

    # 原材料库
    RAW_MATERIALS = [
        {"name": "无氧铜丝", "code": "TM001", "unit": "千克", "category": "导体材料"},
        {"name": "铝合金线材", "code": "TM002", "unit": "千克", "category": "导体材料"},
        {"name": "XLPE绝缘料", "code": "IM001", "unit": "千克", "category": "绝缘材料"},
        {"name": "PVC绝缘料", "code": "IM002", "unit": "千克", "category": "绝缘材料"},
        {"name": "EPR绝缘料", "code": "IM003", "unit": "千克", "category": "绝缘材料"},
        {"name": "PVC护套料", "code": "SM001", "unit": "千克", "category": "护套材料"},
        {"name": "PE护套料", "code": "SM002", "unit": "千克", "category": "护套材料"},
        {"name": "钢带", "code": "AM001", "unit": "千克", "category": "铠装材料"},
        {"name": "钢丝", "code": "AM002", "unit": "千克", "category": "铠装材料"},
        {"name": "铝塑复合带", "code": "AM003", "unit": "千克", "category": "屏蔽材料"},
        {"name": "铜带", "code": "AM004", "unit": "千克", "category": "屏蔽材料"},
        {"name": "填充绳", "code": "FM001", "unit": "千克", "category": "填充材料"},
        {"name": "缠绕带", "code": "BM001", "unit": "千克", "category": "绑扎材料"}
    ]

    # 工艺流程模板
    PROCESS_TEMPLATES = {
        "电力电缆": [
            {"name": "拉丝", "code": "OP010", "std_time": 2.5, "setup_time": 0.5},
            {"name": "绞线", "code": "OP020", "std_time": 3.0, "setup_time": 0.8},
            {"name": "绝缘挤出", "code": "OP030", "std_time": 4.5, "setup_time": 1.2},
            {"name": "成缆", "code": "OP040", "std_time": 3.5, "setup_time": 1.0},
            {"name": "铠装", "code": "OP050", "std_time": 2.8, "setup_time": 0.7},
            {"name": "护套挤出", "code": "OP060", "std_time": 4.0, "setup_time": 1.1},
            {"name": "检验", "code": "OP070", "std_time": 1.5, "setup_time": 0.3}
        ],
        "控制电缆": [
            {"name": "拉丝", "code": "OP010", "std_time": 2.0, "setup_time": 0.4},
            {"name": "绞线", "code": "OP020", "std_time": 2.5, "setup_time": 0.6},
            {"name": "绝缘挤出", "code": "OP030", "std_time": 3.5, "setup_time": 0.9},
            {"name": "成缆", "code": "OP040", "std_time": 3.0, "setup_time": 0.8},
            {"name": "屏蔽", "code": "OP045", "std_time": 2.2, "setup_time": 0.5},
            {"name": "护套挤出", "code": "OP060", "std_time": 3.2, "setup_time": 0.9},
            {"name": "检验", "code": "OP070", "std_time": 1.2, "setup_time": 0.2}
        ],
        "架空线": [
            {"name": "拉丝", "code": "OP010", "std_time": 2.2, "setup_time": 0.5},
            {"name": "绞线", "code": "OP020", "std_time": 3.2, "setup_time": 0.7},
            {"name": "检验", "code": "OP070", "std_time": 1.0, "setup_time": 0.2}
        ]
    }

    # 工作中心配置
    WORK_CENTERS = [
        {"id": "WC001", "name": "拉丝车间1", "type": "拉丝", "capacity": 8},
        {"id": "WC002", "name": "拉丝车间2", "type": "拉丝", "capacity": 6},
        {"id": "WC011", "name": "绞线车间1", "type": "绞线", "capacity": 4},
        {"id": "WC012", "name": "绞线车间2", "type": "绞线", "capacity": 3},
        {"id": "WC021", "name": "挤出车间1", "type": "绝缘挤出", "capacity": 2},
        {"id": "WC022", "name": "挤出车间2", "type": "绝缘挤出", "capacity": 2},
        {"id": "WC031", "name": "成缆车间1", "type": "成缆", "capacity": 3},
        {"id": "WC032", "name": "成缆车间2", "type": "成缆", "capacity": 2},
        {"id": "WC041", "name": "铠装车间", "type": "铠装", "capacity": 2},
        {"id": "WC051", "name": "护套车间1", "type": "护套挤出", "capacity": 2},
        {"id": "WC052", "name": "护套车间2", "type": "护套挤出", "capacity": 1},
        {"id": "WC061", "name": "检验中心", "type": "检验", "capacity": 5}
    ]

    @classmethod
    def generate_realistic_product(cls) -> Dict[str, Any]:
        """生成真实的产品信息"""
        template = random.choice(cls.PRODUCT_TEMPLATES)
        model = random.choice(template["models"])
        spec = random.choice(template["specifications"])
        voltage = random.choice(template["voltage"])

        # 生成产品编码
        product_code = f"{model}-{spec}-{voltage.replace('/', '')}"

        # 生成产品名称
        product_name = f"{model} {spec} {voltage} {template['type']}"

        return {
            "material_id": f"MAT{str(random.randint(100000, 999999))}",
            "material_code": product_code,
            "material_name": product_name,
            "specification": f"{model} {spec}",
            "voltage_level": voltage,
            "product_type": template["type"],
            "unit": template["unit"],
            "material_type": "1",  # 成品
            "drawing_number": f"DWG-{model}-{random.randint(1000, 9999)}",
            "standard_cost": round(random.uniform(8.5, 35.0), 2),
            "material_category": template["type"]
        }

    @classmethod
    def generate_realistic_order(cls, order_num: int) -> Dict[str, Any]:
        """生成真实的生产订单"""
        product = cls.generate_realistic_product()

        # 生成合理的数量（根据产品类型）
        if "架空线" in product["product_type"]:
            planned_qty = random.randint(1000, 10000)  # 架空线通常数量大
        elif "控制电缆" in product["product_type"]:
            planned_qty = random.randint(500, 3000)   # 控制电缆中等数量
        else:
            planned_qty = random.randint(300, 2000)   # 电力电缆

        # 根据订单状态生成完成数量
        status = random.choice(["0", "1", "2", "5", "9"])
        status_names = {"0": "开立", "1": "已审核", "2": "已关闭", "5": "已开工", "9": "已完工"}

        if status in ["0", "1"]:
            completed_qty = 0
        elif status == "5":  # 生产中
            completed_qty = random.randint(0, int(planned_qty * 0.8))
        elif status == "9":  # 已完工
            completed_qty = random.randint(int(planned_qty * 0.95), planned_qty)
        else:  # 已关闭
            completed_qty = random.randint(0, int(planned_qty * 0.3))

        qualified_qty = int(completed_qty * random.uniform(0.92, 0.99))
        scrap_qty = completed_qty - qualified_qty

        # 生成订单时间
        create_date = datetime.now() - timedelta(days=random.randint(1, 30))
        plan_start = create_date + timedelta(days=random.randint(1, 5))
        plan_end = plan_start + timedelta(days=random.randint(3, 20))

        order_id = f"ORD{str(order_num).zfill(8)}"
        order_code = f"MO-{create_date.strftime('%Y%m')}-{str(order_num).zfill(4)}"

        return {
            "id": order_id,
            "code": order_code,
            "product_code": product["material_code"],
            "product_name": product["material_name"],
            "specification": product["specification"],
            "status": status,
            "status_name": status_names[status],
            "planned_quantity": planned_qty,
            "completed_quantity": completed_qty,
            "qualified_quantity": qualified_qty,
            "scrap_quantity": scrap_qty,
            "unit": product["unit"],
            "plan_start_date": plan_start.isoformat(),
            "plan_end_date": plan_end.isoformat(),
            "organization": "天威线缆制造部",
            "department": f"{product['product_type']}车间",
            "priority": random.choice(["高", "中", "低"]),
            "customer": random.choice(["国家电网", "南方电网", "华能集团", "大唐集团", "中石化", "中石油"]),
            "contract_no": f"HT-{create_date.strftime('%Y')}-{random.randint(1000, 9999)}",
            "created_by": random.choice(["张工程师", "李主管", "王经理", "赵技师"]),
            "created_time": create_date.isoformat(),
            "product_info": product
        }

    @classmethod
    def generate_order_materials(cls, product_info: Dict, planned_qty: int) -> List[Dict[str, Any]]:
        """根据产品类型生成所需原材料"""
        materials = []
        product_type = product_info.get("product_type", "电力电缆")

        # 基础材料系数（每米产品需要的材料重量）
        base_factors = {
            "电力电缆": {"导体": 0.8, "绝缘": 0.3, "护套": 0.4, "铠装": 0.2, "填充": 0.1},
            "控制电缆": {"导体": 0.5, "绝缘": 0.2, "护套": 0.2, "屏蔽": 0.1, "绑扎": 0.05},
            "架空线": {"导体": 0.9, "绝缘": 0.1}
        }

        factors = base_factors.get(product_type, base_factors["电力电缆"])

        # 根据产品类型选择材料
        material_mapping = {
            "导体": [m for m in cls.RAW_MATERIALS if m["category"] == "导体材料"],
            "绝缘": [m for m in cls.RAW_MATERIALS if m["category"] == "绝缘材料"],
            "护套": [m for m in cls.RAW_MATERIALS if m["category"] == "护套材料"],
            "铠装": [m for m in cls.RAW_MATERIALS if m["category"] == "铠装材料"],
            "屏蔽": [m for m in cls.RAW_MATERIALS if m["category"] == "屏蔽材料"],
            "填充": [m for m in cls.RAW_MATERIALS if m["category"] == "填充材料"],
            "绑扎": [m for m in cls.RAW_MATERIALS if m["category"] == "绑扎材料"]
        }

        for category, factor in factors.items():
            if category in material_mapping:
                material = random.choice(material_mapping[category])
                required_qty = round(planned_qty * factor * random.uniform(0.9, 1.1), 2)
                issued_qty = round(required_qty * random.uniform(0.8, 1.05), 2)

                materials.append({
                    "material_id": f"RM{random.randint(100, 999)}",
                    "material_code": material["code"],
                    "material_name": material["name"],
                    "required_quantity": required_qty,
                    "issued_quantity": issued_qty,
                    "unit": material["unit"],
                    "issue_type": random.choice(["1", "2"]),
                    "issue_type_name": random.choice(["推式发料", "拉式发料"]),
                    "warehouse_id": f"WH{str(random.randint(1, 5)).zfill(2)}",
                    "warehouse_name": f"{material['category']}仓库",
                    "cost_per_unit": round(random.uniform(15.0, 85.0), 2)
                })

        return materials

    @classmethod
    def generate_order_processes(cls, product_type: str) -> List[Dict[str, Any]]:
        """根据产品类型生成工艺流程"""
        template = cls.PROCESS_TEMPLATES.get(product_type, cls.PROCESS_TEMPLATES["电力电缆"])
        processes = []

        for i, process_template in enumerate(template):
            # 为每个工序分配工作中心
            suitable_wcs = [wc for wc in cls.WORK_CENTERS if process_template["name"] in wc["type"]]
            if not suitable_wcs:
                suitable_wcs = [wc for wc in cls.WORK_CENTERS if "检验" in wc["type"]]

            work_center = random.choice(suitable_wcs)

            processes.append({
                "process_id": f"PROC{str(i + 1).zfill(3)}",
                "process_code": process_template["code"],
                "process_name": process_template["name"],
                "work_center_id": work_center["id"],
                "work_center_name": work_center["name"],
                "standard_hours": process_template["std_time"],
                "actual_hours": round(process_template["std_time"] * random.uniform(0.8, 1.3), 2),
                "setup_time": process_template["setup_time"],
                "process_time": round(process_template["std_time"] - process_template["setup_time"], 2),
                "sequence": (i + 1) * 10,
                "status": random.choice(["pending", "in_progress", "completed"]),
                "operator": random.choice(["操作员A", "操作员B", "操作员C", "操作员D"])
            })

        return processes

    @classmethod
    def generate_inventory_items(cls, count: int = 50) -> List[Dict[str, Any]]:
        """生成库存数据（支持用友标准字段）"""
        inventory_items = []

        # 组织列表
        orgs = ["1891127153005312", "1891127153005313", "1891127153005314"]

        # 物料分类
        manage_classes = [
            {"id": "2000100011111111", "code": "YCL_001", "name": "原材料类"},
            {"id": "2000100011111112", "code": "YCL_002", "name": "辅助材料类"},
            {"id": "2000100011111113", "code": "YCL_003", "name": "半成品类"},
        ]

        for i in range(count):
            material = random.choice(cls.RAW_MATERIALS)
            warehouse_id = f"WH{str(random.randint(1, 5)).zfill(2)}"
            warehouse_code = f"code{random.randint(10, 99)}"
            org = random.choice(orgs)
            manage_class = random.choice(manage_classes)

            # 生成库存数量（考虑实际情况）
            max_stock = random.randint(5000, 50000)
            current_stock = random.randint(int(max_stock * 0.1), max_stock)
            safety_stock = int(max_stock * 0.15)
            available_stock = current_stock - random.randint(0, int(current_stock * 0.1))
            reserved_stock = current_stock - available_stock

            # 生成ID
            material_id = str(random.randint(1921567765125888, 1921567765125999))
            productsku_id = str(random.randint(1921567767616256, 1921567767616350))
            unit_id = str(random.randint(1921568854316950, 1921568854316960))

            # 批次号相关信息
            batch_no = f"BATCH{datetime.now().strftime('%Y%m')}{str(random.randint(100, 999))}"
            production_date = datetime.now() - timedelta(days=random.randint(1, 60))  # 生产日期
            expiry_days = random.randint(180, 730)  # 保质期天数
            expiry_date = production_date + timedelta(days=expiry_days)  # 有效期至
            batch_status = "正常" if expiry_date > datetime.now() else "即将过期" if (expiry_date - datetime.now()).days < 30 else "正常"

            # 库存状态
            stock_status_doc = random.randint(2006555827382257, 2006555827382270)

            inventory_items.append({
                # 原有字段
                "material_id": material_id,
                "material_code": material["code"],
                "material_name": material["name"],
                "warehouse_id": warehouse_id,
                "warehouse_name": f"{material['category']}仓库",
                "current_stock": current_stock,
                "available_stock": available_stock,
                "reserved_stock": reserved_stock,
                "safety_stock": safety_stock,
                "max_stock": max_stock,
                "unit": material["unit"],
                "unit_cost": round(random.uniform(15.0, 85.0), 2),
                "total_value": round(current_stock * random.uniform(15.0, 85.0), 2),
                "last_in_date": (datetime.now() - timedelta(days=random.randint(1, 30))).isoformat(),
                "last_out_date": (datetime.now() - timedelta(days=random.randint(1, 15))).isoformat(),
                "abc_category": random.choice(["A", "B", "C"]),
                "status": "正常" if current_stock > safety_stock else "库存不足",

                # 用友标准新增字段
                "org_id": org,  # 组织ID
                "warehouse_code": warehouse_code,  # 仓库编码
                "productsku_id": productsku_id,  # SKU ID
                "productsku_code": material["code"] + "-SKU01",  # SKU编码
                "productsku_name": material["name"] + "-标准规格",  # SKU名称
                "manage_class_id": manage_class["id"],  # 物料分类ID
                "manage_class_code": manage_class["code"],  # 物料分类编码
                "manage_class_name": manage_class["name"],  # 物料分类名称
                "unit_id": unit_id,  # 计量单位ID
                "batch_no": batch_no,  # 批次号
                "production_date": production_date.isoformat(),  # 生产日期
                "expiry_date": expiry_date.isoformat(),  # 有效期至
                "batch_status": batch_status,  # 批次状态
                "stock_status_doc": stock_status_doc  # 库存状态档案
            })

        return inventory_items

    @classmethod
    def generate_completion_report_data(cls, order_info: Dict) -> Dict[str, Any]:
        """生成完工报告数据"""
        planned_qty = order_info.get("planned_quantity", 1000)
        completed_qty = random.randint(int(planned_qty * 0.8), planned_qty)
        qualified_qty = int(completed_qty * random.uniform(0.95, 0.99))
        scrap_qty = completed_qty - qualified_qty

        return {
            "order_id": order_info["id"],
            "order_code": order_info["code"],
            "product_code": order_info["product_code"],
            "product_name": order_info["product_name"],
            "completed_quantity": completed_qty,
            "qualified_quantity": qualified_qty,
            "scrap_quantity": scrap_qty,
            "return_quantity": random.randint(0, int(completed_qty * 0.02)),
            "efficiency": round(qualified_qty / completed_qty * 100, 2) if completed_qty > 0 else 0,
            "quality_grade": "A级" if qualified_qty / completed_qty >= 0.98 else "B级" if qualified_qty / completed_qty >= 0.95 else "C级",
            "completion_date": datetime.now().isoformat(),
            "shift": random.choice(["白班", "夜班"]),
            "workshop": order_info.get("department", "生产车间"),
            "operator": random.choice(["操作员A", "操作员B", "操作员C"]),
            "inspector": random.choice(["质检员张师傅", "质检员李师傅", "质检员王师傅"]),
            "remarks": random.choice(["正常生产", "设备调试", "工艺改进", "质量提升"])
        }